﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace ThePushCSharp
{
    public class Map
    {
        public Tile[,] tiles;
        public int mapWidth;
        public int mapHeight;
        public Texture2D fogOfWar;
        public GameState state;

        public Map(int mapWidth, int mapHeight, GameState state)
        {
            this.state = state;
            fogOfWar = state.push.Content.Load<Texture2D>("fogofwar");
            tiles = new Tile[mapWidth, mapHeight];
            this.mapWidth = mapWidth;
            this.mapHeight = mapHeight;

            for (int x = 0; x < mapWidth; x++)
            {
                for (int y = 0; y < mapHeight; y++)
                {
                    int rand = GameState.random.Next(7);
                    switch (rand)
                    {
                        case 0:
                            tiles[x, y] = new Tile(new Grassland(state));
                            break;
                        case 1:
                            tiles[x, y] = new Tile(new Beach(state));
                            break;
                        case 2:
                            tiles[x, y] = new Tile(new Forest(state));
                            break;
                        case 3:
                            tiles[x, y] = new Tile(new Ditch(state));
                            break;
                        case 4:
                            tiles[x, y] = new Tile(new Rise(state));
                            break;
                        case 5:
                            tiles[x, y] = new Tile(new Rocks(state));
                            break;
                        case 6:
                            tiles[x, y] = new Tile(new Water(state));
                            break;
                    }
                }
            }
        }

        public void setFoW(Entity entity, int x, int y, int setTo)
        {
            if(x <= 0 || x > mapWidth)
                return;
            if(y <= 0 || y > mapHeight)
                return;

            if (entity != null)
            {
                if (!entity.owner.isAlly(state.gamePlayer))
                    return;

                for (int fx = (-1 * entity.visibility) + x; fx <= entity.visibility + x; fx++)
                {
                    for (int fy = (-1 * entity.visibility) + y; fy <= entity.visibility + y; fy++)
                    {
                        if (fx >= 0 && fx < mapWidth && fy >= 0 && fy < mapHeight)
                        {
                            tiles[fx, fy].friendlyUnitsInSightRange += setTo;
                            if (tiles[fx, fy].friendlyUnitsInSightRange < 0)
                                tiles[fx, fy].friendlyUnitsInSightRange = 0;
                       }
                    }
                }
            }
        }

        public bool setUnit(Entity entity, int x, int y)
        {
            if(x <= 0 || x > mapWidth)
                return false;
            if(y <= 0 || y > mapHeight)
                return false;

            if (entity != null)
            {
                tiles[x, y].unit = entity;
                setFoW(entity, x, y, 1);

                return true;
            }

            return false;
        }

        public void moveUnit(int x, int y, char direction)
        {
            if (x <= 0 || x > mapWidth)
                return;
            if (y <= 0 || y > mapHeight)
                return;

            if (tiles[x, y].unit == null)
                return;

            setFoW(tiles[x, y].unit, x, y, -1); //Leaving area


            switch (direction)
            {
                case 'N': //north
                case 'U': //up
                    if (setUnit(tiles[x, y].unit, x, y + 1))
                        tiles[x, y].unit = null;
                    break;
                case 'S': //south
                case 'D': //down
                    if (setUnit(tiles[x, y].unit, x, y - 1))
                        tiles[x, y].unit = null;
                    break;
                case 'E': //east
                case 'L': //left
                    if (setUnit(tiles[x, y].unit, x + 1, y))
                        tiles[x, y].unit = null;
                    break;
                case 'W': //west
                case 'R': //right
                    if (setUnit(tiles[x, y].unit, x - 1, y))
                        tiles[x, y].unit = null;
                    break;
            }
        }

        public Tile getTile(int x, int y)
        {
            if (x >= 0 && x < mapWidth)
            {
                if (y >= 0 && y < mapHeight)
                {
                    return tiles[x, y];
                }
            }
            return null;
        }
    }
}
